<template>
  <CommonDialog
    v-model="visible"
    :title="title"
    :width="width"
    :loading="loading"
    :confirm-disabled="!canSubmit"
    :confirm-text="isEdit ? '更新' : '创建'"
    @confirm="handleSubmit"
    @cancel="handleCancel"
    @close="handleClose"
  >
    <el-form
      ref="formRef"
      :model="formData"
      :rules="formRules"
      :label-width="labelWidth"
      :label-position="labelPosition"
      :size="size"
      class="form-dialog-content"
    >
      <slot :form="formData" :rules="formRules" />
    </el-form>
  </CommonDialog>
</template>

<script setup>
import { ref, computed, watch, nextTick } from 'vue'
import { ElMessage } from 'element-plus'
import CommonDialog from './CommonDialog.vue'

// Props
const props = defineProps({
  modelValue: {
    type: Boolean,
    default: false
  },
  title: {
    type: String,
    default: '表单'
  },
  width: {
    type: [String, Number],
    default: '600px'
  },
  // 表单数据
  formData: {
    type: Object,
    required: true
  },
  // 表单规则
  formRules: {
    type: Object,
    default: () => ({})
  },
  // 初始数据
  initialData: {
    type: Object,
    default: () => ({})
  },
  // 是否为编辑模式
  isEdit: {
    type: Boolean,
    default: false
  },
  // 加载状态
  loading: {
    type: Boolean,
    default: false
  },
  // 表单配置
  labelWidth: {
    type: String,
    default: '120px'
  },
  labelPosition: {
    type: String,
    default: 'right',
    validator: (value) => ['left', 'right', 'top'].includes(value)
  },
  size: {
    type: String,
    default: 'default',
    validator: (value) => ['large', 'default', 'small'].includes(value)
  },
  // 提交前验证
  beforeSubmit: {
    type: Function,
    default: null
  },
  // 重置表单时保留的字段
  keepFields: {
    type: Array,
    default: () => []
  }
})

// Emits
const emit = defineEmits([
  'update:modelValue',
  'submit',
  'cancel',
  'close',
  'reset'
])

// 响应式数据
const formRef = ref()

// 计算属性
const visible = computed({
  get: () => props.modelValue,
  set: (value) => emit('update:modelValue', value)
})

const canSubmit = computed(() => {
  // 可以根据表单验证状态来决定是否可以提交
  return !props.loading
})

// 方法
const validateForm = async () => {
  try {
    const valid = await formRef.value?.validate()
    return valid
  } catch (error) {
    return false
  }
}

const resetForm = () => {
  formRef.value?.resetFields()
  
  // 重置到初始数据
  const resetData = { ...props.initialData }
  
  // 保留指定字段
  props.keepFields.forEach(field => {
    if (props.formData[field] !== undefined) {
      resetData[field] = props.formData[field]
    }
  })
  
  Object.assign(props.formData, resetData)
  emit('reset')
}

const clearValidate = () => {
  formRef.value?.clearValidate()
}

// 事件处理
const handleSubmit = async () => {
  const isValid = await validateForm()
  if (!isValid) {
    ElMessage.warning('请检查表单填写是否正确')
    return
  }
  
  // 提交前验证
  if (props.beforeSubmit) {
    const canSubmit = await props.beforeSubmit(props.formData)
    if (!canSubmit) return
  }
  
  emit('submit', { ...props.formData })
}

const handleCancel = () => {
  emit('cancel')
}

const handleClose = () => {
  emit('close')
}

// 监听器
watch(visible, (newVal) => {
  if (newVal) {
    nextTick(() => {
      clearValidate()
    })
  } else {
    // 关闭时重置表单
    nextTick(() => {
      resetForm()
    })
  }
})

// 暴露方法给父组件
defineExpose({
  validate: validateForm,
  resetFields: resetForm,
  clearValidate,
  formRef
})
</script>

<style scoped>
.form-dialog-content {
  padding: 0;
}

:deep(.el-form-item) {
  margin-bottom: 20px;
}

:deep(.el-form-item__label) {
  font-weight: 500;
  color: #333;
}

:deep(.el-input),
:deep(.el-select),
:deep(.el-textarea) {
  width: 100%;
}

:deep(.el-form-item__error) {
  position: static;
  margin-top: 4px;
}
</style>